/**
 * @project spring-threadpool-async
 * @description
 * @errorcode SystemException</ br>
 * @author 2022 15:16 huzhengyang Create 1.0 <br>
 * @copyright ©2022-2023
 */

package com.teradata.async.service;


import com.huaweicloud.sdk.core.retry.backoff.SdkBackoffStrategy;
import com.huaweicloud.sdk.ief.v1.model.ListConfigMapsRequest;
import com.huaweicloud.sdk.ief.v1.model.ListConfigMapsResponse;
import com.huaweicloud.sdk.ief.v1.model.ListEdgeNodesRequest;
import com.huaweicloud.sdk.ief.v1.model.ListEdgeNodesResponse;
import com.teradata.async.core.IefCaller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.SuccessCallback;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;

/**
 * @Author HO
 * @Package com.zhitu.thread.service
 * @Description
 * @Date 2020/8/5 10:58
 * @Version 1.0.0
 */
@Service
public class AsyncService {

    protected static final Logger logger = LoggerFactory.getLogger(AsyncService.class);


    @Resource(name = "asyncServiceExecutor")
    private ThreadPoolTaskExecutor asyncServiceExecutor;


    @Autowired
    private IefCaller iefCaller;

    @Async("myTaskAsyncPool") //myTaskAsyncPool为线程池配置类里面的方法，如果使用@Value注解读取配置，则应该改为asyncServiceExecutor（同上面代码的方法名称，可以往上查看）
    public void executeAsync() {
        logger.info("start AsyncService");
        try {
            //逻辑操作
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info("end AsyncService");
    }

    @Async("myTaskAsyncPool")
    public CompletableFuture<ListEdgeNodesResponse> listEdgeNodesAsync() {
        // base delay of retry in milliseconeds
        final int baseDelay = 5000;
        // max backoff time in retry
        final int maxBackoffInMilliseconds = 30000;

        return iefCaller.iefAsyncClient().listEdgeNodesAsyncInvoker(new ListEdgeNodesRequest())
                // max retry times
                .retryTimes(10)
                // Request retry condition, set the retry condition to stop when the job status is success
                .retryCondition((resp, ex) -> Objects.nonNull(resp) && !HttpStatus.valueOf(resp.getHttpStatusCode()).is2xxSuccessful())
                // Request backoff policy, calculate the next request time after each request fails
                // Polling job status requires a long basic delay
                .backoffStrategy(new SdkBackoffStrategy(baseDelay, maxBackoffInMilliseconds))
                .invoke();
    }

    @Async("myTaskAsyncPool")
    public CompletableFuture<ListConfigMapsResponse> listConfigMapsAsync() {
        // base delay of retry in milliseconeds
        final int baseDelay = 5000;
        // max backoff time in retry
        final int maxBackoffInMilliseconds = 30000;

        return iefCaller.iefAsyncClient().listConfigMapsAsyncInvoker(new ListConfigMapsRequest())
                // max retry times
                .retryTimes(10)
                // Request retry condition, set the retry condition to stop when the job status is success
                .retryCondition((resp, ex) -> Objects.nonNull(resp) && !HttpStatus.valueOf(resp.getHttpStatusCode()).is2xxSuccessful())
                // Request backoff policy, calculate the next request time after each request fails
                // Polling job status requires a long basic delay
                .backoffStrategy(new SdkBackoffStrategy(baseDelay, maxBackoffInMilliseconds))
                .invoke();
    }


    public void listenableTaskAsync() {
        ListenableFuture<Object> listenableFuture = asyncServiceExecutor.submitListenable(new Callable<Object>() {
            @Override
            public Object call() throws Exception {

                // base delay of retry in milliseconeds
                final int baseDelay = 5000;
                // max backoff time in retry
                final int maxBackoffInMilliseconds = 30000;

                CompletableFuture<ListEdgeNodesResponse> completableFuture = iefCaller.iefAsyncClient().listEdgeNodesAsyncInvoker(new ListEdgeNodesRequest())
                        // max retry times
                        .retryTimes(10)
                        // Request retry condition, set the retry condition to stop when the job status is success
                        .retryCondition((resp, ex) -> Objects.nonNull(resp) && !HttpStatus.valueOf(resp.getHttpStatusCode()).is2xxSuccessful())
                        // Request backoff policy, calculate the next request time after each request fails
                        // Polling job status requires a long basic delay
                        .backoffStrategy(new SdkBackoffStrategy(baseDelay, maxBackoffInMilliseconds))
                        .invoke();

                completableFuture.thenApply(result -> {
                    System.out.println(result);
                    return result;
                });

                return null;
            }
        });
        listenableFuture.addCallback(new SuccessCallback<Object>() {
            @Override
            public void onSuccess(Object result) {
                return;
            }
        }, new FailureCallback() {
            @Override
            public void onFailure(Throwable ex) {
                return;
            }
        });
    }

}
